#pragma once
#include"thread.hpp"
#include<unordered_map>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<queue>
#include<string.h>

using namespace std;
#define SIZE 1024

class UdpServer
{
public:
    UdpServer(string ip,uint16_t port)
    :_sock(-1)
    ,_ip(ip)
    ,_port(port)
    {

    }
    bool initServer()
    {
        _sock=socket(AF_INET,SOCK_DGRAM,0);
        if(_sock < 0)
        {
            cout<<"socket() failed"<<endl;
            exit(1);
        }
        struct sockaddr_in server;
        bzero(&server,sizeof(server));
        server.sin_family=AF_INET;
        server.sin_port=htons(_port);
        server.sin_addr.s_addr=inet_addr(_ip.c_str());

        if(bind(_sock,(struct sockaddr*)&server,sizeof(server)) < 0)
        {
            cout<<"bind() failed"<<endl;
            exit(3);
        }
    }
    void start()
    {
        char buffer[1024];
        //服务器并不会停止，会持续地进行收发消息
        while(true)
        {
            struct sockaddr_in client;
            bzero(&client,sizeof(client));
            char key[64];
            socklen_t len=sizeof(client);
            ssize_t s=recvfrom(_sock,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&client,len);
            if(s > 0)
            {
                buffer[s]=0;
                string client_ip=inet_ntoa(client.sin_addr);
                uint16_t client_port=inet_htons(client.sin_port);
                snprintf(key,sizeof(key),"%s-%u",client_ip.c_str(),client_port);
                auto it=_users.find(key);
                if(it==_users.end())
                {
                    cout<<"用户列表当中没有这个用户"<<endl;
                    _users.insert({key,client});
                }
            }
            for(auto& iter:_users)
            {
                string sendMessage=key;
                sendMessage+="#";
                sendMessage+=buffer;
                sendto(_sock,sendMessage.c_str(),sendMessage.size(),0,(struct sockaddr*)&client,len);

            }
        }
    }
    ~UdpServer(){
        if(_sock < 0){
            close(_sock);
        }
    }
private:
    int _sock;
    uint16_t _ip;
    string _port;
    unordered_map<string,struct sockaddr_in> _users;
};
// class UdpServer
// {
// public:
//     UdpServer(uint16_t port,string ip="")
//     :_ip(ip)
//     ,_port(port)
//     ,_sock(-1)
//     {

//     }
//     bool initServer()
//     {
//         _sock=socket(AF_INET,SOCK_DGRAM,0);
//         if(_sock < 0)
//         {
//             cout<<"socket() failed"<<endl;
//             exit(1);
//         }
//         struct sockaddr_in server;
//         bzero(&server,sizeof(server));
//         server.sin_family=AF_INET;
//         server.sin_port=htons(_port);
//         server.sin_addr.s_addr=_ip.empty()?INADDR_ANY:inet_addr(_ip.c_str());
//         if(bind(_sock,(struct sockaddr*)&server,sizeof(server)) < 0)
//         {
//             cout<<"bind() failed"<<endl;
//             exit(2);
//         }
//         return true;
//     }
//     void start()
//     {
//         char buffer[SIZE];
//         while(true)
//         {
//             struct sockaddr_in client;
//             bzero(&client,sizeof(client));
//             socklen_t len=sizeof(client);
//             char key[64];
//             ssize_t s=recvfrom(_sock,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&client,&len);
//             if(s > 0)
//             {
//                 buffer[s]=0;
//                 uint16_t client_port=ntohs(client.sin_port);
//                 string client_ip=inet_ntoa(client.sin_addr);
//                 snprintf(key,sizeof(key),"%s-%u",client_ip.c_str(),client.sin_port);
//                 auto it=_users.find(key);
//                 if(it==_users.end())
//                 {
//                     //cout<<"recvfrom() failed"<<endl;
//                     _users.insert({key,client});
//                 }
//             }
//             for(auto& iter:_users)
//             {
//                 string sendMessage=key;
//                 sendMessage+="#";
//                 sendMessage+=buffer;
//                 sendto(_sock,sendMessage.c_str(),sendMessage.size(),0,(struct sockaddr*)&(iter.second),&(iter.second));
//             }
//         }
//     }
//     ~UdpServer(){
//         if(_sock < 0){
//             close(_sock);
//         }
//     }
// private:
//     int _sock;
//     string _ip;
//     uint16_t _port;
//     unordered_map<string,struct sockaddr_in>_users;
// };
// class UdpServer
// {
// public:
//     UdpServer(uint16_t port,std::string ip="")
//     :_ip(ip)
//     ,_port(port),_sock(-1)
//     {

//     }
//     bool initServer()
//     {
//         _sock=socket(AF_INET,SOCK_DGRAM,0);
//         if(_sock < 0)
//         {
//             std::cout<<"socket() failed"<<std::endl;
//             exit(1);
//         }
//         struct sockaddr_in server;
//         bzero(&server,sizeof(server));
//         server.sin_family=AF_INET;
//         server.sin_port=htons(_port);
//         server.sin_addr.s_addr=_ip.empty()?INADDR_ANY:inet_aton(_ip);
//         if(bind(_sock,(struct sockaddr*)&server,sizeof(server)<0))
//         {
//             std::cout<<"bind() failed"<<std::endl;
//             exit(2);
//         }
//         return true;
//     }
//     void start()
//     {
//         char buffer[1024];
//         while(true)
//         {
//             struct sockaddr_in client;
//             bzero(&client,sizeof(client));
//             socklen_t len=sizeof(client);
//             char result[256];
//             char key[64];
//             ssize_t s=recvfrom(_sock,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&client,&len);
//             if(s > 0)
//             {
//                 buffer[s]=0;
//                 uint16_t client_port=ntohs(client.sin_port);
//                 std::string client_ip=inet_ntoa(client.sin_addr);
//                 snprintf(key,sizeof(key),"%s-%u",client_ip.c_str(),client_port);
//                 auto it=_users.find(key);
//                 if(it == _users.end())
//                 {
//                     std::cout<<"用户列表中没有这个用户"<<std::endl;
//                     _users.insert({key,client});
//                 }
//             }
//             for(auto& iter:_users)
//             {
//                 std::string sendMessage=key;
//                 sendMessage+="#";
//                 sendMessage+=buffer;
//                 sendto(_sock,sendMessage.c_str(),sendMessage.size(),0,(struct sockaddr*)&(iter.second),sizeof(iter.second));
//             }
//         }
//     }
//     ~UdpServer()
//     {
//         if(_sock>=0){
//             close(_sock);
//         }
//     }
// private:
//     uint16_t _port;
//     std::string _ip;
//     int _sock;
//     std::unordered_map<std::string,struct sockaddr_in>_users;
//     std::queue<std::string> messageQueue;
// };